\documentclass{article}
\usepackage{ctex}
\usepackage{graphicx, subcaption}

% Language setting
% Replace `english' with e.g. `spanish' to change the document language
\usepackage[english]{babel}

% Set page size and margins
% Replace `letterpaper' with `a4paper' for UK/EU standard size
\usepackage[letterpaper,top=2cm,bottom=2cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}
\geometry{margin=1in}
% Useful packages
\usepackage{amsmath}
\usepackage[colorlinks=true, allcolors=blue]{hyperref}

% SQL语言
\usepackage{listings}
\usepackage{xcolor}

\begin{document}
	
	% 自定义标题页
	\begin{titlepage}
		\begin{center}
			\vspace*{1cm}
			
			% 实验标题
			\Huge
			\textbf{编译原理第三次实验}
			
			\vspace{0.5cm}
			
			\vspace{1.5cm}
			
			% 作者信息表格
			\Large
			\begin{tabular}{rl}
				姓名： & 侯浩然 \\
				班级： & 计算机2106 \\
				学号： & 2211314605 \\
			\end{tabular}
			
			\vfill
			
			% 实验日期
			\Large
			\today
			
		\end{center}
	\end{titlepage}
	
\newpage

	\section{任务一：完成计算器}
		\subsection{任务要求}
		\begin{itemize}
			\item[1] 支持加减乘除、括号、“-”、关系运算等exper操作；
			
			\item[2] 考虑小数
			
			\item[3] 考虑算符结合和优先级；
		\end{itemize}
		
		\subsection{代码分析}
		
		\subsubsection{字符识别}
		
		number 用来匹配所有的数字，包括小数等，当匹配完成时，就返回NUMBER进行规约处理。
		
		当匹配到其他字符包括换行符时，直接返回当前字符，对应的规则匹配失败，然后进入yyerror报错终止程序。
		
		yywrap始终返回1,模拟到达文件结尾，然后等待下一次的输入。
		
		\begin{figure}[tbph!]
			\centering
			\includegraphics[width=0.7\linewidth]{screenshot005}
			\caption{}
			\label{fig:screenshot005}
		\end{figure}
		
		
		\subsubsection{小数处理}
		由于要考虑小数的情况，所以这里采用简易的操作，将所有的数都看作double类型，定义 YYSTYPE 为 double 类型，然后定义变量 NUMBER 用来装载返回值。
		
		\subsubsection{优先级设置}
		根据经验设置，括号的优先级最高，其次是乘除，然后是加减，在然后是比较符号，最后是赋值符号。
		
		所以进行如下优先级配置：
		
		\begin{figure}[tbph!]
				\centering
		\subcaptionbox{小数设置}{
			\includegraphics[width = .45\linewidth]{screenshot001}
		}
		\subcaptionbox{优先级设置}{
			\centering
			\includegraphics[width = .45\linewidth]{screenshot002}
		}
		\end{figure}

\newpage
		
		\subsubsection{规则设置}
		
		S用来处理换行，并且产生E，E用来处理各种计算符号和识别出来的数字。
		
		\begin{figure}[tbph!]
			\centering
			\includegraphics[width=0.7\linewidth]{screenshot003}
			\caption{}
			\label{fig:screenshot003}
		\end{figure}
		
		\subsubsection{主函数及错误处理}
		
		最后在主函数中调用词法分析器，当检测到不匹配的规则时，转到yyerror进行错误输出。
		
		\begin{figure}[tbph!]
			\centering
			\includegraphics[width=0.7\linewidth]{screenshot004}
			\caption{}
			\label{fig:screenshot004}
		\end{figure}
		
\newpage
			
		\subsection{运行结果}
			通过执行如下命令，得到最终可运行程序：
			
			lex tokens.l
			
			bison parser.y
			
			gcc lex.yy.c parser.tab.c
			
			./a.out
			
						
			然后使用如下数据集进行验证：
			
			4.0 * (1 + 4) // 输出20
			
			4.0 * 1 + 4   // 输出8
			
			6 = ( 1 + 4 ) // 输出 assign 5
			
			7 > 9         // 输出 0
			
			6 < 9 // 输出 1
			
			a x 1 + 6 // 报错
			
			\begin{figure}[tbph!]
				\centering
				\includegraphics[width=0.7\linewidth]{screenshot006}
				\caption{}
				\label{fig:screenshot006}
			\end{figure}
			
			
			
			
		
		
		
	\section{任务二：错误处理}
		\subsection{字符识别}
			首先修改匹配规则，将字符串等进行识别输出，并且要把用到的运算符也进行匹配，其中返回值的定义在bison中写明。
					
			
			\begin{figure}[tbph!]
				\centering
				\subcaptionbox{匹配模式}{
					\includegraphics[width = .65\linewidth]{screenshot007}
				}
				\subcaptionbox{优先级设置}{
					\centering
					\includegraphics[width = .29\linewidth]{screenshot008}
				}
			\end{figure}

\newpage
			
		\subsection{规约规则}
		
		添加上识别字符串的非终结符R，并打印其输出。
		
		其中需要添加S --> S E R 用来生成任意位置的字符串来进行匹配。
		
		\begin{figure}[tbph!]
			\centering
			\subcaptionbox{匹配模式}{
				\includegraphics[width = .6\linewidth]{screenshot010}
			}
			\subcaptionbox{优先级设置}{
				\centering
				\includegraphics[width = .35\linewidth]{screenshot011}
			}
		\end{figure}
		
		
		\subsection{运行结果}
		
		最终的运行结果如上图，只要字符串不出现在运算表达式中间，都可以进行计算，并输出字符串的值。


	
	
\end{document}

